package com.aspire.boc.mms.wmf.action;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlrpc.XmlRpcException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.aspire.boc.mms.wmf.cam.Admin;
import com.aspire.boc.mms.wmf.constants.GlobalConstant;
import com.aspire.boc.mms.wmf.model.ExtJsTreeNode;
import com.aspire.boc.mms.wmf.model.SecurityGroup;
import com.aspire.boc.mms.wmf.model.SecurityUser;
import com.aspire.boc.mms.wmf.model.WmfResource;
import com.aspire.boc.mms.wmf.model.WmfRole;
import com.aspire.boc.mms.wmf.permission.PermissionCacheService;
import com.aspire.boc.mms.wmf.service.PermissionService;
import com.aspire.boc.mms.wmf.util.AuthAnnotation.NoAuth;
import com.aspire.boc.mms.wmf.util.Configuration;
import com.aspire.boc.mms.wmf.util.PermissionUtil;
import com.aspire.boc.mms.wmf.util.ResourceManager;
import com.aspire.boc.mms.wmf.util.Util;
import com.aspire.boc.mms.wmf.util.ValidateCode;

@Controller
public class IndexAct extends BaseAct {

	private static Log log = LogFactory.getLog(IndexAct.class);
	static ResourceManager rm = ResourceManager.getInstance();
	
	@Autowired
	private PermissionService permissionService;
	
	@Autowired
	private PermissionCacheService permissionCacheService;

	@NoAuth(value = "IndexAct.index")
    //@RequestMapping(value = "/index")
    public String sendVerifycode(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
	    
	    String userid = null;
        String sendVerifyCode = rm.getValue("sendVerifyCode");
        // 判断是否发送验证码，sendVerifyCode[true:是，false:否]
        if("true".equals(sendVerifyCode)) {
            Boolean needSendVarifyCode = (Boolean) session.getAttribute("varifycode.send.need");
            // 判断是否在session生命周期内已发送验证码:[是: 不再发送, 否: 发送]
            if(needSendVarifyCode==null || needSendVarifyCode) {
                // 验证
                try {
                    Admin currentUser = getCurrentUserInfo(session);
                    userid = currentUser.getAdminName();
                    log.info("current user[userid:"+userid+"]");
                    session.setAttribute("admin", currentUser);
                    long code = Math.round(Math.random() * 899999) + 100000;
                    session.setAttribute("sessionVerifycode", code + "");
                    log.info("[" + userid + "][verifycode:" + code + "]");
                    // 发送验证码到手机
                    if (currentUser.getMobile() != null && currentUser.getMobile().length() > 0
                            && !"13800138000".equals(currentUser.getMobile())) {
                        Util.sendSMSSocket(currentUser.getMobile(), "您的登录验证码是" + code);
                    }
                    // 发送验证码到邮箱
                    if (currentUser.getEmail() != null && currentUser.getEmail().length() > 0) {
                        Util.sendMail(currentUser.getEmail(), "您的登录验证码是" + code, "登录验证码");
                    }
                    return "/verifycode.jsp";
                } catch (Exception e) {
                    log.error("[userName:" + userid + "] validateLogin error ",
                            e);
                    return "/verifycode.jsp";
                }
            }
        }
        return index(request, response, session);
	}

	@NoAuth(value = "IndexAct.index")
	//@RequestMapping(value = "/checkVerifycode")
	public String checkVerifycode(HttpServletRequest request,
			HttpServletResponse response, HttpSession session) {
		
	    // 取得用户是否输入验证码
        String verifycode = request.getParameter("verifycode");
        Admin currentUser = null;
        try {
            currentUser = getCurrentUserInfo(session);
        } catch(Exception e) {
            log.error(">>>>fail to get current user", e);
            return "/verifycode.jsp";
        }
        String userid = currentUser.getAdminName();
        log.info("current user[userid:"+userid+"]");
        // 判断输入的验证码是否为空
	    if (StringUtils.isBlank(verifycode)) {
            // 已经下发验证码，但是没有输入
	        request.setAttribute("verifycodeError", Boolean.TRUE);
            log.info("[userid:" + userid + "][not input]");
            return "/verifycode.jsp";
        } 
	    
	    String sessionVerifycode = (String) session.getAttribute("sessionVerifycode");
	    if(sessionVerifycode == null) {
            log.error(">>>>fail to get verify code of user[userid="+userid+"] ");
            return "/verifycode.jsp";
        }
	    if(verifycode.equals(sessionVerifycode)) {
	        // 进入页面
            session.setAttribute("varifycode.send.need", Boolean.FALSE);
            log.info(">>>>success to check varify code of user[userid="+userid+"]");
            return index(request, response, session);
	    }
	    
        log.info(">>>>>>>>>user login error ! verifycode error! ");
        request.setAttribute("verifycodeError", Boolean.TRUE);
        return "/verifycode.jsp";
	}

	private String index(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
		// TODO Auto-generated method stub
		return null;
	}

	@NoAuth(value = "IndexAct.login")
	@RequestMapping(value = "/login")
	public String login(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
		
		return "login.jsp";
	}
	
	@NoAuth(value = "IndexAct.validateCode")
	@RequestMapping(value = "/validateCode")
	@ResponseBody
	public Object validateCode(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
		
		ValidateCode validateCode = new ValidateCode(120, 30, 4, 50);
		String code = validateCode.getCode();
		log.info("validate code generated: " + code);
		session.setAttribute("validateCode", code);
		
		HashMap<String, String> result = new HashMap<String, String>(1);
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ImageIO.write(validateCode.getBuffImg(), "png", baos);
			byte[] imageBytes = baos.toByteArray();
			String imageBase64String = Base64.encodeBase64String(imageBytes);
			result.put("image", imageBase64String);
			log.info("success to convert image to base64 string");
		} catch (IOException e) {
			log.error("fail to convert image to base64 string", e);
		}
		return result;
	}
	
	@NoAuth(value = "IndexAct.index")
	@RequestMapping(value = "/index")
	public String index(
			Model model,
			String username, String password, @RequestParam(value = "vcode", required = false) String validateCode,
			HttpServletRequest request, HttpServletResponse response, HttpSession session) {
	    
		model.addAttribute("username", username);
		model.addAttribute("password", password);
		model.addAttribute("vcode", validateCode);
		String mainPage = "init.jsp";
		// 用户已登陆，直接跳转管理台主页
		Object sessionSecurityUser = session.getAttribute("securityUser");
		if(sessionSecurityUser != null) {
			return mainPage;
		}
		// 用户未登陆，验证登陆信息
		String errorMsg = checkLoginInfo(username, password, validateCode, session);
		if(errorMsg != null) {
			model.addAttribute("errorMsg", errorMsg);
			return "login.do";
		}
		// 用户身份验证失败，返回登陆页面
		try {
            SecurityUser securityUser = permissionCacheService.getSecurityUserByLoginName(username);
            session.setAttribute("securityUser", securityUser);
			// 是否为系统管理员
			boolean isSystemAdmin = securityUser.isSystemAdmin();
			List<SecurityGroup> securityGroups = permissionCacheService.getGroupsByLoginName(username);
			//Set<Group> groups = CamUtil.getGroupsByUserName(loginName);
			if (securityGroups == null || securityGroups.size() == 0) {
				throw new Exception(">>>>>>>>user login (" + username + ") goroup : " + securityGroups);
			}
			log.info(">>>>>>>>>user login (" + username + ") goroup : " + securityGroups);
			
			List<String> groupIds = new ArrayList<String>();
			for (SecurityGroup group : securityGroups) {
				if (!groupIds.contains(group.getGid()))
					groupIds.add(String.valueOf(group.getGid()));
			}
			// 非系统管理员，需要加载角色与授权请求
			if(!isSystemAdmin) {
			    // 加载角色数据
			    List<WmfRole> roles = permissionService.getWmfRolesByGId(groupIds);
	            log.info(">>>>>>>>>user login (" + username + ") roles : " + roles);
	            if (roles == null || roles.size() == 0) {
	                return mainPage;
	            }
	            List<String> roleIds = new ArrayList<String>();
	            for (WmfRole role : roles) {
	                if (!roleIds.contains(role.getId()))
	                    roleIds.add(role.getId());
	            }
	            request.getSession().setAttribute(GlobalConstant.ADMIN_ROLEIDS, roleIds);
	            // 加载授权请求数据
	            HashSet<String> actiondos = permissionService.getUserActiondos(roleIds);
	            if(actiondos!=null && actiondos.size()>0) {
	                session.setAttribute(GlobalConstant.WMF_USER_ACTIONDOS, actiondos);
	            }
	            log.info(">>>>>>>>>all user action .do loaded: "+actiondos);
			}
			
			request.getSession().setAttribute("groupIds", groupIds);
			return mainPage;

		} catch (Exception e) {
			log.info(">>>>>>>>>user login error !");
			log.error("[userName:" + username + "] Login error ", e);
			session.invalidate();
			return "/error.jsp";
		}
	}

	/**
	 * 校验用户登陆信息
	 * @param username
	 * @param password
	 * @param validateCode
	 * @return
	 */
	private String checkLoginInfo(String username, String password, String validateCode, HttpSession session) {

		SecurityUser securityUser = permissionCacheService.getSecurityUserByLoginName(username);
		if(securityUser == null) {
			return "用户名或密码错误！";
		}
		String sessionValidateCode = (String) session.getAttribute("validateCode");
		if(sessionValidateCode == null) {
			return "图形验证码错误！";
		}
		String dbPassword = securityUser.getPassword();
		String loginPassword = Base64.encodeBase64String(password.getBytes());
		if(!dbPassword.equals(loginPassword) ) {
			return "用户名或密码错误！";
		}
		
		if(!sessionValidateCode.equalsIgnoreCase(validateCode)) {
			return "图形验证码错误！";
		}
		return null;
	}

	/**
	 * 程序入口 登录前，登录入口，跳转到logon.jsp
	 **/
	@RequestMapping("/logon")
	public void logon(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
	}

	/**
	 * logoff
	 * 
	 * @throws Exception
	 */
	@RequestMapping("/logoff")
	public void logoff(HttpServletRequest request,
			HttpServletResponse response, HttpSession session) throws Exception {
		
		session.invalidate();
		response.sendRedirect("index.html");
	}

	/**
	 * loadtree
	 * 
	 * @return json
	 * 
	 * @throws Exception
	 */
	@RequestMapping("/loadTree")
	public @ResponseBody
	List<ExtJsTreeNode> loadTree(
			@RequestParam(value = "node", required = true) String pid,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		List<ExtJsTreeNode> nodes = new ArrayList<ExtJsTreeNode>();
		
		SecurityUser securityUser = (SecurityUser) request.getSession().getAttribute("securityUser");
        if(securityUser == null) {
        	return  noAuthorityTree();
        }
        // 判断是否为系统管理员
        boolean isAdmin = securityUser.isSystemAdmin();
		@SuppressWarnings("unchecked")
        List<String> roleIds = (List<String>) request.getSession().getAttribute(GlobalConstant.ADMIN_ROLEIDS);
		if (!isAdmin && (roleIds == null || roleIds.size() == 0)) {
			return noAuthorityTree();
		}
		List<Integer> acitonsIntegers = null;
		List<WmfResource> resourceList = null;
		
		if (isAdmin) {
			resourceList = permissionCacheService.getResourcesPid(pid, true);
		} else {
			acitonsIntegers = permissionService.getActionsByRole(roleIds);
			List<WmfResource> authorizedResources = permissionCacheService.getAuthorizedResources(acitonsIntegers);
			if(authorizedResources == null || authorizedResources.isEmpty()) {
				return noAuthorityTree();
			}
			resourceList = new ArrayList<WmfResource>(authorizedResources.size());
			for(WmfResource resource : authorizedResources) {
				BigDecimal parentid = resource.getParentid();
				if(parentid == null || !pid.equals(parentid.intValue() + "")) {
					continue;
				}
				resourceList.add(resource);
			}
			//resourceList = permissionCacheService.getResourcesActionId(acitonsIntegers, pid, isAdmin);
		}

		if (resourceList == null || resourceList.size() == 0) {
			return noAuthorityTree();
		}
		// 菜单按orderid排序
		resourceList = sortResourcesByOrderId(resourceList);
		for (int i = 0; i < resourceList.size(); i++) {
			WmfResource resource = (WmfResource) resourceList.get(i);
			ExtJsTreeNode node = new ExtJsTreeNode();
			node.setId(String.valueOf(resource.getId()));
			node.setPID(pid);
			node.setIsRoot(false);
			node.setLeaf(!resource.getIsleaf().equals("N"));
			node.setText(resource.getName());
			node.setEnname(resource.getEnname());
			node.setHref("");
			node.setHrefTarget(resource.getTarget());
			node.setIconCls(resource.getIcon());
			node.setQtip(resource.getHint());
			boolean isOpen = !resource.getIsopen().equals("N");
			node.setExpanded(node.getLeaf() ? false : isOpen);
			nodes.add(node);
		}
		return nodes;
	}

	/**
	 * 菜单按orderid排序
	 * @param resourceList
	 * @return
	 */
	private List<WmfResource> sortResourcesByOrderId(List<WmfResource> list) {

		Collections.sort(list, new Comparator<WmfResource>() {

			@Override
			public int compare(WmfResource o1, WmfResource o2) {

				Short orderid1 = o1.getOrderid();
				Short orderid2 = o2.getOrderid();
 				if(orderid1 == null) return -1;
 				if(orderid2 == null) return 1;
				return orderid1.compareTo(orderid2);
			}
		});
    	return list;
	}

	/**
	 * 未得到权限树节点
	 * 
	 * @Title: NoAuthorityTree
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @return
	 */
	private List<ExtJsTreeNode> noAuthorityTree() {
		List<ExtJsTreeNode> nodes = new ArrayList<ExtJsTreeNode>();
		ExtJsTreeNode node = new ExtJsTreeNode();
		node.setId("1");
		node.setPID("0");
		node.setIsRoot(true);
		node.setLeaf(true);
		node.setText("无访问权限");
		node.setEnname("No Authority");
		node.setHref("#");
		node.setHrefTarget("");
		node.setIconCls("");
		nodes.add(node);
		return nodes;
	}

	private String getPermissionUrl() {
		String permissionUrl = Configuration.getConfiguration("system.permission.url");
		String[] urlList = (Configuration.getConfiguration("system.permission.url")
				+ "|" + Configuration.getConfiguration("system.back.url")).split("\\|");
		for (String urlStr : urlList) {
			try {
				URL url = new URL(urlStr);
				HttpURLConnection con = (HttpURLConnection) url
						.openConnection();
				con.setConnectTimeout(Integer.parseInt(Configuration.getConfiguration("system.permission.url.timeout")));
				con.setRequestMethod("POST");
				int state = con.getResponseCode();
				if (state == 200) {
					permissionUrl = urlStr;
					break;
				}
			} catch (Exception e) {
				log.info("[permission url error][" + urlStr + "]", e);
				continue;
			}
		}
		return permissionUrl;
	}
	
	/**
     * @param session
     * @return
     * @throws MalformedURLException
     * @throws XmlRpcException
     */
    @SuppressWarnings("unchecked")
    private Admin getCurrentUserInfo(HttpSession session) throws MalformedURLException, XmlRpcException {

        
        Admin admin = new Admin();
        String userid = (String) session.getAttribute("edu.yale.its.tp.cas.client.filter.user");
        String url = getPermissionUrl();
        String system_def = Configuration.getConfiguration("system.permission.system_def");;
        
        Vector<Object> params = new Vector<Object>();
        params.add(system_def);
        params.add(userid);
        // 取得用户信息
        Map<String, Object> userHash = null;
        try {
            userHash = (Map<String, Object>) PermissionUtil.execXmlRpc(url, "UserService.getUserInfo", params);
        } catch (Exception e) {
            log.error(Thread.currentThread().getName() + " - fail to call cam service[UserService.getUserInfo][UserId:"+userid+"]", e);
        }
        if(userHash == null) {
            return admin;
        }
        admin.setAdminName((String) userHash.get("user_name"));
        admin.setMobile((String) userHash.get("mobile"));
        admin.setEmail((String) userHash.get("email"));
        admin.setTruename((String) userHash.get("real_name"));
        admin.setSex((String) userHash.get("sex"));
        return admin;
    }

}
